package com.ncloud.system.service.impl;

import java.util.Date;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.github.pagehelper.PageInfo;
import com.ncloud.common.enmus.ResultEnum;
import com.ncloud.common.exception.UserException;
import com.ncloud.common.utils.EncryptUtils;
import com.ncloud.common.utils.PageHelperUtils;
import com.ncloud.common.utils.RedisUtils;
import com.ncloud.system.constant.UserConstant;
import com.ncloud.system.entity.User;
import com.ncloud.system.mapper.UserMapper;
import com.ncloud.system.service.CompanyService;
import com.ncloud.system.service.SequenceService;
import com.ncloud.system.service.UserRoleService;
import com.ncloud.system.service.UserService;

@Service
public class UserServiceImpl implements UserService {
	@Autowired
	private UserMapper userMapper;
	@Autowired
	private RedisUtils redisUtils;
	@Autowired
	private SequenceService sequence;
	@Autowired
	private UserRoleService userRoleService;
	@Autowired
	private CompanyService companyService;
	
	@Override
	public User findByUsername(String username) {
		return userMapper.findByUsername(username);
	}
	
	@Override
	public User findByUserId(Long userId) {
		User user = userMapper.findByUserId(userId);
		if(user !=null){
			List<String> roles = userRoleService.getRolesByUserId(userId);
			user.setRoles(roles);
		}
		return user;
	}
	
	private User getUser(Long userId){
		User user = userMapper.findByUserId(userId);
		if(user == null){
			throw new UserException(ResultEnum.USER_NOT_FOUND);
		}
		return user;
	}

	@Override
	public List<User> findByDepartId(Long departId) {
		List<User> userList = userMapper.findByDepartId(departId);
		return userList;
	}
	
	@Override
	public void lockUser(Long userId) {
		checkCompanyLock(userId);
		// 锁定用户
		userMapper.changeUserState(userId,UserConstant.USER_STATE_LOCK);
		refreshUserRedis(userId);
	}
	
	private void refreshUserRedis(Long userId) {
		User user = userMapper.findByUserId(userId);
		if(redisUtils.exists(UserConstant.REDIS_USER_INFO_PREFIX+user.getAccount())){
			redisUtils.set(UserConstant.REDIS_USER_INFO_PREFIX+user.getAccount(), user, UserConstant._USER_INFO_USERNAME_EXPIRETIME);
			redisUtils.setSeq(UserConstant.REDIS_ERROR_TIME_PREFIX+user.getAccount(), 0);
		}
	}

	@Override
	public void unLockUser(Long userId) {
		checkCompanyLock(userId);
		// 锁定用户
		userMapper.changeUserState(userId,UserConstant.USER_STATE_NORMAL);
		refreshUserRedis(userId);
	}

	private User checkCompanyLock(Long userId) {
		User user = getUser(userId);
		Integer state = companyService.getCompanyStateById(user.getCompanyId().intValue());
		if(state.intValue()==1){
			throw new UserException(ResultEnum.COMPANY_LOCK);
		}
		return user;
	}

	@Override
	public void updateFirstLoginTime(User user) {
		userMapper.updateFirstLoginTime(user.getUserId(),user.getFirstLoginTime());
	}

	@Override
	public int getRoleUsers(Long roleId) {
		return userMapper.getRoleUsers(roleId);
	}
	@Override
	public void resetPassword(Long userId, String password) {
		checkCompanyLock(userId);
		userMapper.updatePassword(userId,EncryptUtils.encryptSHA(password));
		refreshUserRedis(userId);
		//清空redis用户登录信息
		//redisUtils.remove(keys);
	}

	@Override
	public Object getUsers(JSONObject json) {
		Object object=null;
		Long roleId = json.getLong("roleId");
		Long departId = json.getLong("departId");
		Long companyId = json.getLong("companyId");
		String account = json.getString("account");
		if(PageHelperUtils.isPage(json)){
			PageHelperUtils.setPageParam(json);
			List<Map<String, Object>> userList = userMapper.getUsers(companyId,departId,roleId,account);
			@SuppressWarnings({ "rawtypes", "unchecked" })
			PageInfo pageInfo = new PageInfo(userList);
			object = JSON.parseObject(JSON.toJSONString(pageInfo));
		}else{
			List<Map<String, Object>> userList = userMapper.getUsers(companyId,departId,roleId,account);
			object = JSON.parseArray(JSON.toJSONString(userList));
		}
		
		return object;
	}

	@Override
	public void checkPassword(Long userId, String password) {
		if(StringUtils.isBlank(password)){
			throw new UserException(ResultEnum.PARAM_ERROR);
		}

		User user = findByUserId(userId);
		if(user==null){
			throw new UserException(ResultEnum.USER_NOT_FOUND);
		}

		if(!user.getPasswd().equals(EncryptUtils.encryptSHA(password))){
			throw new UserException(ResultEnum.USER_PASSWD_ERROR);
		}
	}

	@Override
	public void setUserHead(Long userId, String filePath) {
		userMapper.setUserHead(userId,filePath);
	}

	@Override
	public void deleteUser(Long userId) {
		User user = checkCompanyLock(userId);
		dealDelete(user);
	}
	
	private void dealDelete(User user) {
		userMapper.deleteUser(user.getUserId());
		redisUtils.remove(UserConstant.REDIS_USER_INFO_PREFIX+user.getAccount());
		redisUtils.remove(UserConstant.REDIS_ERROR_TIME_PREFIX+user.getAccount());
	}

	@Override
	public void deleteUserByDepartId(Long departId) {
		List<User> userList = findByDepartId(departId);
		userMapper.deleteuserByDepartId(departId);
		for (User user : userList) {
			dealDelete(user);
		}
	}

	@Override
	@Transactional
	public void addUser(JSONObject json) {
		User user = JSON.parseObject(json.toJSONString(), User.class);
		// 整理user参数
		if(user.getCompanyId()==null || user.getDepartId() == null || StringUtils.isBlank(user.getAccount())
			|| StringUtils.isBlank(user.getPasswd()) ||StringUtils.isBlank(user.getName()) || StringUtils.isBlank(user.getState())
			|| StringUtils.isBlank(user.getContactPhone()) || user.getRoles().isEmpty()){
			throw new UserException(ResultEnum.PARAM_ERROR);
		}
		// 校验企业是否锁定
		Integer state = companyService.getCompanyStateById(user.getCompanyId().intValue());
		if(state==1){
			throw new UserException(ResultEnum.COMPANY_LOCK);
		}
		Long userId = sequence.getSequence("user_id_seq");
		Long operId = Long.parseLong(json.getString("operId"));
		user.setUserId(userId);
		user.setPasswd(EncryptUtils.encryptSHA(user.getPasswd()));
		user.setIcon("");
		user.setCreateUser(operId);
		user.setCreateDate(new Date());
		user.setUpdateDate(new Date());
		user.setUpdateUser(operId);
		userMapper.save(user);
		userRoleService.createUserRole(userId,user.getRoles());
	}

	@Override
	@Transactional
	public void updateUser(JSONObject json) {
		if(!json.containsKey("userId") || json.getLong("userId") == null){
			throw new UserException(ResultEnum.PARAM_ERROR);
		}
		Long userId = json.getLong("userId");
		User user = checkCompanyLock(userId);
		
		if(user !=null && json.containsKey("roles") && !json.getJSONObject("roles").isEmpty()){
			JSONObject roles = json.getJSONObject("roles");
			if(roles.containsKey("addRoles")){
				JSONArray roleaArray = roles.getJSONArray("addRoles");
				List<String> addList = roleaArray.toJavaList(String.class);
				userRoleService.createUserRole(userId, addList);
			}
			if(roles.containsKey("delRoles")){
				userRoleService.deleteUserRole(userId, roles.getJSONArray("delRoles").toJavaList(Long.class));
			}
			json.remove("roles");
		}
		
		User mUser = JSON.parseObject(json.toJSONString(), User.class);
		BeanUtils.copyProperties(mUser, user);
		user.setUpdateDate(new Date());
		user.setUpdateUser(json.getLong("operId"));
		userMapper.updateUser(user);
	}

	@Override
	public boolean isExists(String userName) {
		if(StringUtils.isNotBlank(userName)){
			User user = findByUsername(userName);
			if(user!=null && user.getUserId().intValue()>0){
				return true;
			}
		}
		return false;
	}

	@Override
	public void lockUserByCompany(Long companyId) {
		List<Map<String, Object>> userList = userMapper.getUsers(companyId, null, null, null);
		for (Map<String, Object> map : userList) {
			Long userId = (Long) map.get("userId");
			userMapper.changeUserState(userId,UserConstant.USER_STATE_LOCK);
			refreshUserRedis(userId);
		}
	}

	@Override
	public void unLockUserByCompany(Long companyId) {
		List<Map<String, Object>> userList = userMapper.getUsers(companyId, null, null, null);
		for (Map<String, Object> map : userList) {
			Long userId = (Long) map.get("userId");
			userMapper.changeUserState(userId,UserConstant.USER_STATE_NORMAL);
			refreshUserRedis(userId);
		}
	}

}
